<?php

namespace plugin\laoha\app\controller;

use support\Request;
use plugin\admin\app\common\Util;
use plugin\admin\app\model\Role;
use plugin\laoha\app\model\Act;

class Crud
{
    protected $noNeedLogin = ['index', 'list', 'select', 'show','init','add','act'];

    /**
     * @var Model
     */

    protected $model = null;
    protected $builder = false;
    protected $set = [];

    //权限列表
    protected $rules = [];

    //私有者id
    protected $private_id = 0;


    //多人会员字段
    protected $menbers = [];

    /**
     * 是否数据限制
     * 请使用 null||'personal'||'auth' 
     * personal时有$dataLimitField，$private_id不为空，私有或会员可增加记录，如博客，群组
     * auth时私有或会员可管理记录，所有会员多能操作记录，如BBS  时$private_id为版主，menbers为副版主
     * 不指定$private_id时，  personal一般会员可添加记录，auth时，一般只有后台管理人员可添加记录
     */

    protected $dataLimit = 'auth';

    /**
     * 数据限制字段,开启私有必须指定$dataLimitField
     * 大多情况下是user_id
     */
    protected $dataLimitField = '';


    //验证字段类设置
    protected $validate = false;

    /**
     * 审核
     * 此权限由管理权限附带
     */
    public function check(Request $request)
    {
        if (!($this->canAccess('manage') || $this->canAccess('admin'))){
            if(request()->api){
                return json_fail('无权限');
            }else{
                return false;
            }         
        }
        $data = $request->all();
        if (empty($data['ids']) && empty($data['id'])){
            if(request()->api){
                return json_fail('操作记录未指定');
            }else{
                return false;
            }            
        }
        $ids = empty($data['ids']) ? $data['id'] : $data['ids'];
        //var_export($data);
        if ($this->serverBatchUpdate($ids, $data)) {
            if(request()->api){
                return json_ok('操作完成');
            }else{
                return true;
            }            
        } else {
            if(request()->api){
                return json_ok('操作失败');
            }else{
                return false;
            }              
        }
    }

    public function add(Request $request,$params=[]){
        if(empty($params)) $params = $request->all();
        $add = empty($params['del'])? true : false;
        if(empty($params['field']) || (empty($params['id']) && empty($params['ids']))){
            return json_fail('操作失败');
        }
        if(!in_array($params['field'],$this->model->getAddFields())){
            return json_fail('操作失败');
        }else{
            if(!empty($params['id'])){
                $re = $add?$this->model->where('id',$params['id'])->increment($params['field']):$this->model->where('id',$params['id'])->where($params['field'],'>',0)->decrement($params['field']);
                return json_ok('操作成功');
            }else{
                $ids = str2arr($params['ids']);
                $re = $add?$this->model->whereIn('id',$ids)->increment($params['field']):$this->model->whereIn('id',$ids)->where($params['field'],'>',0)->decrement($params['field']);
                return json_ok('操作成功');
            }
        } 
    }

    public function act(Request $request)
    {
        $root = $request->input('root', '');
        $id = $request->input('id', '');
        $act = $request->input('act', '');
        $del = $request->input('del', '') ? true : false;
        if (empty($root) || empty($id) || empty($act) || !user_id() || !in_array($act,$this->model->getActs())) { 
			//$msg = "$root|$id|$act|".in_array($act,$this->model->getActs());
            return json_fail('操作失败');
        }
        $model = new Act;
        if ($del) {
            $model->del($root, $id, $act);
        } else {
            $model->add($root, $id, $act);
        }
        return json_ok('操作成功');
    }

    /**
     * 列表
     * @param $request
     */
    public function list(Request $request)
    {
        $builder = $this->builder ?: $this->model;
        $set = array_merge($request->all(), $this->set);
        $data = laoha_query($builder, $set, $this->model);  
        if(request()->api){
            return json_ok($data);
        }else{
            return $data;
        }               
    }

    /**
     * 查询
     * @param $request
     */
    public function select(Request $request)
    {
        $builder = $this->builder ?: $this->model;
        $set = array_merge($request->all(), $this->set);
        $set['page_type'] = 3;
        $data = laoha_query($builder, $set);
        if(request()->api){
            return json_ok($data);
        }else{
            return $data;
        }   
    }



    public function show(Request $request)
    {
        $type = empty($request->input('edit')) ? 'show' : 'edit';
        $id = $request->input('id');
        if (empty($id)) {
            if(request()->api){
                return json_fail('记录未指定');
            }else{
                return false;
            }   
        }
        if ($fields = $request->input('fields')) {
            $data = $this->model->select(str2arr($fields))->find($id);
        } else {
            $data = $this->model->find($id);
        }

        if ($data) {
            $data = $data->toArray();
            if (method_exists($this->model, 'out_data')) {
                $data = $this->model->out_data($data, $type);
            }
            if(request()->api){
                return json_ok($data);
            }else{
                return $data;
            }               
        } else {
            if(request()->api){
                return json_fail('记录未找到');
            }else{
                return false;
            }                 
        }
    }


    /**
     * 新建
     * @param $id
     * @param $data
     */
    public function store(Request $request)
    {
        //群组式，博客类
        if ($this->dataLimit == 'personal' && $this->private_id && !($this->canAccess('private') || $this->canAccess('menber'))) {  //私有
            if(request()->api){
                return json_fail('无权限');
            }else{
                return false;
            } 
        }
        $data = $request->post();
        if ($this->validate && !$this->validate->scene('create')->check($data)) {
            if(request()->api){
                return json_fail($this->validate->getError());
            }else{
                return $this->validate->getError();
            } 
        } else {
            $password_filed = 'password';
            if (isset($data[$password_filed])) {
                $data[$password_filed] = Util::passwordHash($data[$password_filed]);
            }
            if ($data = $this->serverStore($data)) {
                if(request()->api){
                    return json_ok($data);
                }else{
                    return true;
                }                 
            } else {
                if(request()->api){
                    return json_fail('新建失败,无权限或未知错误');
                }else{
                    return false;
                } 
            }
        }
    }



    /**
     * 更新
     * @param $id,$ids
     * @param $data
     */
    public function update(Request $request)
    {
        $data = $request->all();
        //有批操作权限
        $pass = ($this->canAccess('manage') || $this->canAccess('private') || ($this->dataLimit == 'auth' && $this->canAccess('menber'))) ? true : false;
        if (!$pass && !$this->dataLimitField) {  //没有用户字段
            if(request()->api){
                return json_fail('无权限');
            }else{
                return false;
            } 
        }


        if (isset($data['id'])) {
            $password_filed = 'password';
            if (isset($data[$password_filed])) {
                // 密码为空，则不更新密码
                if ($data[$password_filed] === '') {
                    unset($data[$password_filed]);
                } else {
                    $data[$password_filed] = Util::passwordHash($data[$password_filed]);
                }
            }
            if ($this->validate && !$this->validate->scene('update')->check($data)) {                
                if(request()->api){
                    return json_fail($this->validate->getError());
                }else{
                    return $this->validate->getError();
                } 
            }
            $id = $data['id'];
            unset($data['id']);
            if ($data = $this->serverUpdate($id, $data)) {
                if(request()->api){
                    return json_ok($data);
                }else{
                    return $data;
                } 
            } else {
                if(request()->api){
                    return json_fail('记录更新失败,出现未知错误');
                }else{
                    return false;
                } 
            }
        } elseif (isset($data['ids'])) {
            $ids = $data['ids'];
            if ($this->serverBatchUpdate($ids, $data)) {
                if(request()->api){
                    return json_ok('指定记录更新成功');
                }else{
                    return true;
                } 
            } else {
                if(request()->api){
                    return json_fail('记录更新失败,出现未知错误');
                }else{
                    return false;
                } 
            }
        } else {
            if(request()->api){
                return json_fail('未指定id');
            }else{
                return false;
            } 
        }
    }


    /**
     * 删除
     */
    public function delete(Request $request)
    {
        $id  = $request->input('id');
        $ids = false;
        if (!$id) {
            $ids = $request->input('ids');
            if ($ids) {
                $id = $ids;
            } else {
                if(request()->api){
                    return json_fail('未指定id');
                }else{
                    return false;
                } 
            }
        }

        $data = $request->all();
        //有批操作权限
        $pass = ($this->canAccess('manage') || $this->canAccess('private') || ($this->dataLimit == 'auth' && $this->canAccess('menber'))) ? true : false;
        if (!$pass && !$this->dataLimitField) {  //没有用户字段
            if(request()->api){
                return json_fail('无权限');
            }else{
                return false;
            } 
        }

        unset($data['id']);
        unset($data['ids']);

        if ($m = $this->serverDelete($id, $data)) {
            if(request()->api){
                return json_ok($m . '条记录删除成功');
            }else{
                return true;
            }             
        } else {
            if(request()->api){
                return json_fail('0条记录删除成功');
            }else{
                return false;
            }       
        }
    }

    /**
     * 不检查权限
     * @param $data
     * @return bool
     */
    protected function serverStore($data)
    {
        $columns = getfields($this->model);
        foreach ($data as $k => $v) {
            if (in_array($k, $columns)) {
                $this->model->setAttribute($k, $v);
            }
        }
        if($this->model->save()){
            return $this->model->toArray();
        }else{
            return false;
        }
        
    }

    /** 
     * @param $primaryKey
     * @param $data
     *
     * @return bool
     */
    protected function serverUpdate($id, $ndata)
    {
        $dis_update_fields = ['id'];
        $columns = getfields($this->model);
        if ($this->dataLimitField && !($this->canAccess('manage') || $this->canAccess('private') || ($this->dataLimit == 'auth' && $this->canAccess('menber')))) {
            $data = $this->model->where($this->dataLimitField, user_id())->find($id);
            //禁止用户修改字段
            $dis_update_fields = array_merge($dis_update_fields,[$this->dataLimitField], $this->model->dis_update_fields());
        } else {
            $data = $this->model->find($id);
            //$data = method_exists($this->model,'user') ? $this->model->with(['user:id,nickname,avatar'])->find($id) : $this->model->find($id);
        }
        if(empty($data)) return false;
        foreach ($ndata as $k => $v) {
            if (!in_array($k, $columns) || in_array($k, $dis_update_fields)) {
                continue;
            }
            $data->setAttribute($k, $v);
        }
        if($data->save()){
            return $data->toArray();
        }else{
            return false;
        }
    }



    /**
     * 批量修改 
     */
    protected function serverBatchUpdate($id, $data)
    {
        $dis_update_fields = ['id'];
        $columns = getfields($this->model);
        if ($this->dataLimitField && !($this->canAccess('manage') || $this->canAccess('private') || ($this->dataLimit == 'auth' && $this->canAccess('menber')))) {
            //禁止用户修改字段
            $dis_update_fields = array_merge($dis_update_fields, [$this->dataLimitField],$this->model->dis_update_fields());
        }
        $id = str2arr($id);
        foreach ($data as $k => $v) {
            if (!in_array($k, $columns) || in_array($k, $dis_update_fields)) {
                unset($data[$k]);
            }
        }
        if ($this->dataLimitField && !($this->canAccess('manage') || $this->canAccess('private') || ($this->dataLimit == 'auth' && $this->canAccess('menber')))) {
            //返回修改记录数，此操作不触发saved等事件
            return $this->model->whereIn('id', $id)->where($this->dataLimitField, user_id())->update($data);
        } else {
            return $this->model->whereIn('id', $id)->update($data);
        }
    }




    /**
     * @param string $ids
     *
     * @return mixed
     */
    protected function serverDelete($id)
    {
        if (is_string($id) && strpos($id, ',')) {
            $id = str2arr($id);
        }
        if (is_array($id)) {
            if ($this->dataLimitField && !($this->canAccess('manage') || $this->canAccess('private') || ($this->dataLimit == 'auth' && $this->canAccess('menber')))) {
                $data = $this->model->where($this->dataLimitField,user_id())->whereIn('id', $id)->get();
            }else{
                $data = $this->model->whereIn('id', $id)->get();
            }            
            if(empty($data)) return false;
            $n = 0;
            foreach ($data as $d) {
                if ($d->delete()) $n++;
            }
            return $n;
        } else {
            if ($this->dataLimitField && !($this->canAccess('manage') || $this->canAccess('private') || ($this->dataLimit == 'auth' && $this->canAccess('menber')))) {
                $data = $this->model->where($this->dataLimitField,user_id())->find($id);
            }else{
                $data = $this->model->find($id);
            }
            if(empty($data)) return false;
            return $data->delete();
        }
    }


    //检查是否有方法权限
    protected function canAccess($name = '', $user_id = 0)
    {
        if ($name == 'owner') {  //类似所有者之权
            return $this->owner($user_id);
        }
        $rules = ($this->rules) ?: $this->getRules();
        return $rules[$name] ?? false;
    }


    protected function getRules()
    {
        $rules = $this->getAccess();
        $rules = array_fill_keys($rules, true);
        $this->rules = $rules;
        return $this->rules;
    }



    /**
     * 取权限列表
     * 返回 array
     */
    protected function getAccess()
    {
        $permision = [];
        //后台用户
        if (admin_id() && $roles = admin('roles')) {
            // 角色没有规则
            $rules = Role::whereIn('id', $roles)->pluck('rules')->toArray();
            if (in_array('*', $rules) || in_array('#', $rules)) {  //超级管理员
                $permision[] = 'manage';
            }
        }

        if ($this->private_id && user_id() == $this->private_id) {
            $permision[] = 'private';   //私权
        }

        if ($this->menbers && in_array(user_id(), $this->menbers)) {
            $permision[] = 'menber';   //会员
        }
        return $permision;
    }

    /**
     * 检测是否本人
     */
    protected function owner($user_id = 0)
    {
        if (empty($user_id)) return false;
        return (user_id() === $user_id) ? true : false;
    }

    /**
     * 私有权限
     */
    protected function prevate_rule()
    {
        if ($this->private_id && user_id() == $this->private_id) {
            $this->rules['private'] = true;   
        }else{
            $this->rules['private'] = false; 
        }
        return $this->rules['private'];
    }
    
    /**
     * 会员权限
     */    
    protected function menber_rule()
    {
        if ($this->menbers && in_array(user_id(), $this->menbers)) {
            $this->rules['menber'] = true;   
        }else{
            $this->rules['menber'] = false; 
        }
        return $this->rules['menber'];
    }

    /**
     * 输出
     */
    protected function out($data=[],$tpl=''){   
        if(request()->api){  //api
            if(is_string($data)){
                return json_fail($data);
            }else{
                return json_ok($data);
            }
        }else{
            if($tpl){
                return view($tpl,$data);
            }else{
                return view('error',['msg'=>arr2str($data)],null,'laoha');
            }
        }
    }

}
